﻿using PBO.Data;
using PBO.Game.BattleLog;
using PBO.Game.Img;
using PBO.Util;
using PokemonBattle.BattleNetwork;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace PBO.Forms.NetworkForm.BattleForm
{
    public partial class BattleObserverForm : Form
    {
        //public BattleObserverForm()
        //{
        //    InitializeComponent();
        //}

        #region props

        protected BattleLogger Logger { get; set; }

        private string _serverAddress;

        private byte _observePosition;
        private Image _terrainImage;

        private Bitmap _image = new Bitmap(256, 144);
        private List<Rectangle> _pokemonRects;
        private List<Rectangle> _pokemonStateRects;
        private List<int> _positions;

        private List<int> _indices;
        protected PokemonBattleClient _client;
        private BattleSnapshot _snapshot;
        private BattleMode _mode;

        #endregion

        #region log msg

        private static void OutMsg(RichTextBox rtb, string msg, Color color)
        {
            if (rtb.InvokeRequired)
            {
                rtb.Invoke(new Action(() => OutMsg(rtb, msg, color)));
            }
            else
            {
                rtb.SelectionStart = rtb.Text.Length;
                rtb.SelectionColor = color;
                rtb.AppendText(msg + "\r\n");
                rtb.ScrollToCaret();
            }
        }

        private void AddMsg(string msg, Color color)
        {
            OutMsg(this.rbLog, msg, color);
        }

        #endregion

        public BattleObserverForm(string address, byte observePosition)
        {
            InitializeComponent();

            this.Icon = Properties.Resources.PokemonBall;
            this.Logger = new BattleLogger();
            this.Logger.LogAdded += this.AddMsg;
            this.Logger.LogAdded += (s, e) => UpdateScreen();
            _serverAddress = address;
            _observePosition = observePosition;

            picScreen.Image = _image;
        }

        private void InitializeClient()
        {
            _client = new PokemonBattleClient(_serverAddress);
            _client.OnConnected += ConnectedServer;
            _client.OnSetBattleInfo += ReceiveBattleInfo;
            _client.OnSetSnapshot += ReceiveSnapshot;
            _client.OnDisconnected += OnDisconnected;
        }
        protected virtual void ConnectServer()
        {
            _client.Initialize();
            _client.RunThread();
        }

        protected virtual void ConnectedServer()
        {
            _client.RegistObserver(0);
        }
        private void ReceiveBattleInfo(BattleInfo info)
        {
            CheckCustomData(info.CustomDataHash);
            _terrainImage = ImageHelper.GetTerrainImage(info.Terrain);
            _mode = info.Mode;
            SetCaption(info.Caption);
        }
        private void CheckCustomData(string hash)
        {
            //if (GameService.CustomData.DataHash != hash)
            //    imgtxt.AddText("当前使用的自定义数据与对战不同,观战时可能会出现错误");
        }
        private void ReceiveSnapshot(BattleSnapshot snapshot)
        {
            _snapshot = snapshot;
            Color textColor = Color.FromArgb(snapshot.TextColor);
            Logger.AppendText(snapshot.NewText, textColor);
        }
        protected virtual void OnDisconnected()
        {
            Logger.AppendText("与主机断开了连接", Color.Red);
        }

        private void SetCaption(string txt)
        {
            if (!InvokeRequired)
            {
                this.Text = txt;
            }
            else
            {
                Invoke(new Action<string>(SetCaption), txt);
            }
        }

        private void UpdateScreen()
        {
            List<PokemonSnapshot> pokemons = _snapshot.Pokemons.Elements;

            if (_positions == null)
            {
                _positions = new List<int>();
                _indices = new List<int>();
                if (_mode == BattleMode.Double_4P || _mode == BattleMode.Double)
                {
                    if (_observePosition > 2)
                    {
                        _positions.AddRange(new int[] { 2, 3, 0, 1 });
                        _indices.AddRange(new int[] { 2, 2, 1, 1 });
                    }
                    else
                    {
                        _positions.AddRange(new int[] { 0, 1, 2, 3 });
                        _indices.AddRange(new int[] { 1, 1, 2, 2 });
                    }
                }
                else if (_observePosition == 2)
                {
                    _positions.AddRange(new int[] { 1, 0 });
                    _indices.AddRange(new int[] { 2, 1 });
                }
                else
                {
                    _positions.AddRange(new int[] { 0, 1 });
                    _indices.AddRange(new int[] { 1, 2 });
                }
            }

            if (_pokemonRects == null)
            {
                _pokemonRects = new List<Rectangle>();
                _pokemonStateRects = new List<Rectangle>();
                if (pokemons.Count == 2)
                {
                    _pokemonRects.Add(new Rectangle(20, 64, 80, 80));
                    _pokemonStateRects.Add(new Rectangle(136, 95, 120, 38));

                    _pokemonRects.Add(new Rectangle(155, 13, 80, 80));
                    _pokemonStateRects.Add(new Rectangle(-6, 27, 126, 30));
                }
                else
                {
                    _pokemonRects.Add(new Rectangle(0, 64, 80, 80));
                    _pokemonRects.Add(new Rectangle(50, 64, 80, 80));
                    _pokemonStateRects.Add(new Rectangle(130, 87, 126, 30));
                    _pokemonStateRects.Add(new Rectangle(136, 116, 126, 30));

                    _pokemonRects.Add(new Rectangle(126, 3, 80, 80));
                    _pokemonRects.Add(new Rectangle(175, 7, 80, 80));
                    _pokemonStateRects.Add(new Rectangle(0, 1, 126, 30));
                    _pokemonStateRects.Add(new Rectangle(-6, 29, 126, 30));
                }
            }
            using (Graphics graph = Graphics.FromImage(_image))
            {
                graph.DrawImageUnscaled(_terrainImage, 0, 0);
                for (int i = 0; i <= pokemons.Count / 2 - 1; i++)
                {
                    int position = _positions[i];

                    Image stateImage = ImageHelper.GetPMStateImg(_indices[i], pokemons[position]);
                    if (stateImage != null)
                        graph.DrawImageUnscaled(stateImage, _pokemonStateRects[i]);
                    if (pokemons[position].Hp > 0 && !pokemons[position].Hid)
                    {
                        Image pmImage = default(Image);
                        if (pokemons[position].Substituded)
                        {
                            pmImage = PBO.Game.Properties.Resources.SubBack;
                        }
                        else
                        {
                            PokemonData pm = GameService.GetPokemon(pokemons[position].Identity);
                            if (pokemons[position].Gender == (byte)PokemonGender.Female && pm.BackImageF != -1)
                            {
                                pmImage = GameService.GetImage(pokemons[position].Identity, pm.BackImageF);
                            }
                            else
                            {
                                pmImage = GameService.GetImage(pokemons[position].Identity, pm.BackImage);
                            }
                        }
                        graph.DrawImageUnscaledAndClipped(pmImage, _pokemonRects[i]);
                    }
                }
                for (int i = pokemons.Count / 2; i < pokemons.Count; i++)
                {
                    int position = _positions[i];
                    Image stateImage = ImageHelper.GetPMStateImg(_indices[i], pokemons[position]);
                    if (stateImage != null)
                        graph.DrawImageUnscaled(stateImage, _pokemonStateRects[i]);

                    if (pokemons[position].Hp > 0 && !pokemons[position].Hid)
                    {
                        Image pmImage = default(Image);
                        if ((pokemons[position].Substituded))
                        {
                            pmImage = PBO.Game.Properties.Resources.Substitute;
                        }
                        else
                        {
                            PokemonData pm = GameService.GetPokemon(pokemons[position].Identity);
                            if (pokemons[position].Gender == (byte)PokemonGender.Female && pm.FrontImageF != -1)
                            {
                                pmImage = GameService.GetImage(pokemons[position].Identity, pm.FrontImageF);
                            }
                            else
                            {
                                pmImage = GameService.GetImage(pokemons[position].Identity, pm.FrontImage);
                            }
                        }
                        graph.DrawImageUnscaledAndClipped(pmImage, _pokemonRects[i]);
                    }
                }
            }
            SetImage();
        }

        private void SetImage()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(SetImage));
            }
            else
            {
                picScreen.Refresh();
            }
        }

        #region event

        private void BattleObserverForm_Load(object sender, EventArgs e)
        {
            int logLine = Convert.ToInt32(Properties.Settings.Default.LogLineCount);
            if (logLine > 6)
            {
                rbLog.Size = new Size(256, 7 + logLine * 13);
                this.Size = new Size(291, 206 + logLine * 13);
            }
            InitializeClient();
            ConnectServer();
        }

        private void BattleObserverForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_client != null)
            {
                _client.Stop();
                _client = null;
            }
        }

        #endregion

    }
}
